#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <functional>
#include "Connection.hpp"

class HandlerConnection
{
public:
    HandlerConnection(func_t func):_func(func)
    {}
    void HandlerRecv(Connection *conn)
    {
        // 因为recv出错会返回错误码，二错误码全局只会有一个，所以为了防止其他代码中的错误码干扰，这里需要设置一下错误码
        errno = 0;
        LOG(DEBUG, "HandlerRecv fd : %d\n", conn->Sockfd());
        while (true)
        {
            char buffer[1024];
            int n = ::recv(conn->Sockfd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                conn->AppendInBuffer(buffer);
            }
            else
            {
                // 本轮数据读完了
                if (errno == EWOULDBLOCK || errno == EAGAIN)
                {
                    break;
                }
                else if (errno == EINTR) // 信号终端
                {
                    continue;
                }
                else // 读取出错
                {
                    // 错误统一处理
                    conn->_excpter(conn);
                    return;
                }
            }
        }
        _func(conn);// 上层回调
    }
    void HandlerSender(Connection *conn)
    {
        errno = 0;
        while (true)
        {
            ssize_t n = ::send(conn->Sockfd(), conn->OutBuffer().c_str(), conn->OutBuffer().size(), 0);
            if (n > 0)
            {
                // n 实际发送了多少
                conn->OutBufferRemove(n);
                if (conn->OutBufferEmpty()) break;
            }
            else if (n == 0)
            {
                break;
            }
            else
            {
                // 本轮数据读完了
                if (errno == EWOULDBLOCK || errno == EAGAIN)
                {
                    break; // 只有这个会跳出循环， 向下执行
                }
                else if (errno == EINTR) // 信号终端
                {
                    continue;
                }
                else // 读取出错
                {
                    // 错误统一处理
                    conn->_excpter(conn);
                    return;
                }
            }
        }

        // 这里一定遇到了，发送缓冲区被写满的情况
        if (!conn->OutBufferEmpty())
        {
            conn->_R->EnableReadWrite(conn->Sockfd(), true, true);// 开启对写事件关心
        }
        else
        {
            conn->_R->EnableReadWrite(conn->Sockfd(), true, false); // 关闭写事件
        }

    }
    void HandlerExcepter(Connection *conn)
    {
        errno = 0;
        // 1. 去掉epoll对该文件fd的关心
        // 2. 服务器关闭sockfd
        // 3. 释放connection
        conn->_R->RemoveConnection(conn->Sockfd());
    }
private:
    func_t _func;
};